// -*- c++ -*-
//
//  File:         ecga.cpp
//
//  Description:  C++ implementation of the class ecga.
//                Contains the ECGA loop.
//
//  Author:       Fernando Lobo
//
//  Date:         June/1999
//
//  Modified to be compliant with gcc 3.4 by Kumara Sastry
//  Date:        March/2006

#include "ecga.hpp"


//extern randomG RANDOM;

//----------------------------------------------------------
ecga::ecga(parameter *pra, randomG * rndga, Validator * val) {
		pr=pra;
		rndg=rndga;
		// first population with random individuals
		//
		pop = new population( pr->popsize,pr, rndg );       
		pop->random();  
		pop->evaluate(val);
		pop->statistics();
		}





void ecga::report( std::ofstream &outfile, population *pop, int gen )
{
  //
  // get information about the best individual in the population
  //
  chromosome bestChrom;
  bestChrom = (*pop)[ pop->best() ];

  //
  // print it
  //
  std::cout << "generation      : " << gen << std::endl
       << "best fitness    : " << pop->maxfit() << std::endl
       << "avg fitness     : " << pop->avgfit() << std::endl
       << "best chromosome : " << bestChrom << std::endl
       << "------------------------------------------------------------"
       << std::endl;

  outfile << "Generation " << gen << std::endl;
  outfile << *pop;
}

bool ecga::done( population *pop, int gen )
{
  switch(pr->stop_criteria )
   {
     case ALLELE_CONVERGENCE : return sc_allele_conv( *pop, gen );
     case MAX_GENERATIONS    : return sc_maxgen( *pop, gen,pr );
     default: 
        {printf("[ERROR] ECGA:stop_criteria: %d",pr->stop_criteria); 
		error("This should never happen.");
		}
   }
}

//
// runs the ECGA and sends output information to the 'outfile'.
//
Popolazione * ecga::run(Validator * val, int step_size)
{
  int gen=0;
  /*
   *If it happen that the evolvable algorithm is called when it thinks to have already found the individuals with the best score what it does is to make a new evaluations of all his element.
   *this allows it to check if the old best is really so good or if it was only "luck" during the previous evaluation.
   *
   */
  if(pop->maxfit()!=val->getMaxScore())
	{
	pop->evaluate(val);
	pop->statistics();
	}
	/*
	*The generational loop...
	*
	*/
  while(/* !done( pop, gen ) &&*/ (pop->maxfit()!=val->getMaxScore()) && gen < step_size)      
    { 
	  //printf("PHASE 0\n");      
      gen++;
      //
      // apply selection
      //
      population *temp_pop = new population( pop->popsize(),pr,rndg );
      pop->selection( temp_pop );
	  //printf("PHASE 1\n");      
      delete pop;     // delete unnecessary temporary
      pop = temp_pop;

      //
      // model the population with a greedy MPM search
      //
      mpm MPM( pr->lchrom,pr );   
      MPM.model( pop);  
      //if( parameter::report_MPM ) std::cout << "MPM: " << MPM << std::endl;

      //
      // generate a new population using the MPM
      //
      temp_pop = new population( pop->popsize(),pr,rndg ); 
      MPM.generate( pop, temp_pop,rndg );  
	  //printf("PHASE 2\n");
      delete pop;
      pop = temp_pop;
      
      //
      // evaluate individuals and do the report
      //
      pop->evaluate(val);  
      pop->statistics();
	  printf("[INFO] ECGAcore::ecga - Population max %f,min %lf, avg %lf\n",pop->maxfit(),pop->minfit(),pop->avgfit());                                
     // report( outfile, pop, gen );
    }
  //
  // cleanup
  //
  //printf("[INFO] ECGAcore::ECGA complited procedure\n");
  chromosome * bestcr= pop->getBest();
  char strout[1024];
  bestcr->asString(strout);
	 //delete pop;
	//RETURN:
	int i,j,p;
	int array[DEF_COLS][DEF_ROWS][LUT_SIZE];
	for(i=0;i< DEF_COLS;i++)
		{
		for(j=0;j<DEF_ROWS;j++)
			{
			for(p=0;p<LUT_SIZE;p++)
				{
				char buff = strout[p+LUT_SIZE*j+DEF_ROWS*i];
				array[i][j][p]=atoi(&buff);
				}
			}
		}
	Popolazione *P;
	Individuo *In[1];
	In[0] = new Individuo();
	//assign DNA from array
	In[0]->arrayInit(array);
	//In[0]->print_geno();
	P= new Popolazione(1);
	P->load_list(1,In);
	val->valuta_pop(P);
	//P->print_all(); 
	return P;
}
